package com.sun.filesigndemo.common.security;


import com.sun.filesigndemo.bussiness.mapper.UserMapper;
import com.sun.filesigndemo.common.entity.User;
import com.sun.filesigndemo.common.security.Realm.Principal;
import com.sun.filesigndemo.common.utils.Encodes;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * 用户工具类
 * @author Winkey
 * @version 2017-11-06
 */
@Component
public class UserUtils {

	protected static Logger logger = LoggerFactory.getLogger(UserUtils.class);

	public static final String USER_CACHE = "userCache:";

	public static final String CACHE_AUTH_INFO = "authInfo";
	
	public static final String HASH_ALGORITHM = "SHA-1";
	public static final int HASH_INTERATIONS = 1024;
	public static final int SALT_SIZE = 8;

	private static final Long USER_CATCH_TIME_OUT= 3600L; // 1小时

	private static UserMapper userMapper;
	
	@Autowired
	public UserUtils(UserMapper userMapper) {
		UserUtils.userMapper= userMapper;
	}
	
	public static Principal getPrincipal(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Principal principal = (Principal)subject.getPrincipal();
			if (principal != null){
				return principal;
			}
//			subject.logout();
		}catch (UnavailableSecurityManagerException e) {
			
		}catch (InvalidSessionException e){
			
		}
		return null;
	}
	
	public static Session getSession(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Session session = subject.getSession(false);
			if (session == null){
				session = subject.getSession();
			}
			if (session != null){
				return session;
			}
//			subject.logout();
		}catch (InvalidSessionException e){
			
		}
		return null;
	}
	
	// ============== User Cache ==============
	
	public static Object getCache(String key) {
		return getCache(key, null);
	}
	
	public static Object getCache(String key, Object defaultValue) {
//		Object obj = getCacheMap().get(key);
		Object obj = getSession().getAttribute(key);
		return obj==null?defaultValue:obj;
	}

	public static void putCache(String key, Object value) {
//		getCacheMap().put(key, value);
		getSession().setAttribute(key, value);
	}

	public static void removeCache(String key) {
//		getCacheMap().remove(key);
		getSession().removeAttribute(key);
	}
	
	/**
	 * 生成安全的密码，生成随机的16位salt并经过1024次 sha-1 hash
	 */
	public static String entryptPassword(String plainPassword) {
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] salt = Digests.generateSalt(SALT_SIZE);
		byte[] hashPassword = Digests.sha1(plain.getBytes(), salt, HASH_INTERATIONS);
		return Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword);
	}
	
	/**
	 * 验证密码
	 * @param plainPassword 明文密码
	 * @param password 密文密码
	 * @return 验证成功返回true
	 */
	public static boolean validatePassword(String plainPassword, String password) {
		String plain = Encodes.unescapeHtml(plainPassword);
		byte[] salt = Encodes.decodeHex(password.substring(0,16));
		byte[] hashPassword = Digests.sha1(plain.getBytes(), salt, HASH_INTERATIONS);
		return password.equals(Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword));
	}
	
	public static void main(String[] args) {
		System.out.println(entryptPassword("123456"));
	}
	
	/**
	 * 是否是验证码登录
	 * @param useruame 用户名
	 * @param isFail 计数加1
	 * @param clean 计数清零
	 * @return
	 */
	public static boolean isValidateCodeLogin(String useruame, boolean isFail, boolean clean){
		String key= "loginFailMap:" + useruame;
		Object loginFail = CacheUtils.getExp(key);
		Integer loginFailNum;

		if (loginFail == null){
			loginFailNum= 0;
		} else {
			loginFailNum= Integer.valueOf(loginFail + "");
		}
		if (isFail){
			loginFailNum++;
			CacheUtils.setExp(key, loginFailNum, USER_CATCH_TIME_OUT);
		}
		if (clean){
			CacheUtils.delete(key);
		}
		return loginFailNum >= 5;
	}
	
	
	/**
	 * 根据ID获取用户
	 * @param id
	 * @return 取不到返回null
	 */
	private static User get(Long id){
		User user;
		try {
			user = CacheUtils.getExp(USER_CACHE + id);
		} catch (Exception e){
			user = null;
			logger.error("获取用户缓存错误：", e);
		}
		if (user ==  null){
			user = userMapper.selectByPrimaryKey(id);
			if (user == null){
				return null;
			}
			CacheUtils.setExp(USER_CACHE + user.getId(), user, USER_CATCH_TIME_OUT);
		}
		return user;
	}

	private static User upCache(User user){
		if (user !=  null){
			CacheUtils.setExp(USER_CACHE + user.getId(), user, USER_CATCH_TIME_OUT);
		}
		return user;
	}

	/**
	 * 清除指定用户缓存
	 * @param user
	 */
	public static void clearCache(User user){
		CacheUtils.delete(USER_CACHE + user.getId());
	}
	
	/**
	 * 清除指定用户缓存
	 */
	public static void clearCache(Long id){
		CacheUtils.delete(USER_CACHE + id);
	}
	/**
	 * 清除指定用户缓存
	 */
	public static void clearCache(){
		CacheUtils.delete(USER_CACHE + getUser().getId());
	}
	
	/**
	 * 获取当前用户
	 * @return 取不到返回 new User()
	 */
	public static User getUser(){
		Principal principal = getPrincipal();
		if (principal!=null){

			User user = get(principal.getId());
			if (user != null){
				return user;
			}
			return new User();
		}
		// 如果没有登录，则返回实例化空的User对象。
		return new User();
	}
	
}
